package com.dj.service.serviceimpl;

import ca.uhn.fhir.rest.param.StringParam;
import com.dj.bean.PatientBean;
import com.dj.bean.PatientHistoryBean;
import com.dj.constant.FhirContextContstant;
import com.dj.repository.PatientHistoryRespository;
import com.dj.repository.PatientRespository;
import com.dj.service.PatientService;
import org.apache.commons.collections4.CollectionUtils;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Meta;
import org.hl7.fhir.dstu3.model.Patient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author cyf
 * @description
 * @create 2018-06-27 13:45
 **/

@Service
public class PatientServiceImpl implements PatientService {

    private static final Logger logger = LoggerFactory.getLogger(PatientServiceImpl.class);

    @Autowired
    private PatientRespository patientRespository;

    @Autowired
    private PatientHistoryRespository patientHistoryRespository;



    @Transactional
    @Override
    public IdType savePatient(Patient patient) {
        //将patient转换为json串
        //此处也可以转成xml FhirContextContstant.getXMLParse().encodeResourceToString(patient);
        String content = FhirContextContstant.getParse().encodeResourceToString(patient);

        //获得实体对象
        PatientBean patientBean = getPatientBean(patient, content, FhirContextContstant.INITIAL_VERSION_NUMBER, null);
        //保存到库
        return saveOrUpdate(content, patientBean, FhirContextContstant.INITIAL_VERSION_NUMBER);
    }


    @Transactional
    @Override
    public IdType updatePatient(String id, Patient patient) {
        IdType idType = new IdType();

        // 判断数据库中是否存在id的患者
        Optional<PatientBean> result = null;
        try {
            result = patientRespository.findById(id);
            logger.info("Current object existence, the patient id is {}",id);
        } catch (Exception e) {
            logger.error("findById query error ", e);
        }

        if (!result.isPresent()) {
            //记录不存在
            logger.error("patient id={} is not present!!!", id);
            return idType;
        }
        // 根据id查询的bean
        PatientBean patientBean = result.get();
        String version = result.get().getVersion();

        // 记录存在
        String content = FhirContextContstant.getParse().encodeResourceToString(patient);
        //更新 version + 1
        version = String.valueOf(Integer.parseInt(version) + 1);
        return saveOrUpdate(content, getPatientBean(patient, content, version, patientBean), version);
    }

    /**
     * 设置数据库表fhir_patient_record信息
     * @param patient
     * @param content
     * @param version
     * @param patientBean
     * @return
     */
    private PatientBean getPatientBean(Patient patient, String content, String version, PatientBean patientBean) {
        Date date = new Date();
        if(patientBean==null){
            patientBean = new PatientBean();
            patientBean.setCreateTime(date);
        }
        patientBean.setVersion(version);
        patientBean.setContent(content);
        //记录每次更新的时间
        patientBean.setParam1(date);

        //患者姓名patient.getNameFirstRep().getText()
        patientBean.setName(patient.getNameFirstRep().getText());

        return patientBean;
    }

    /**
     * 保存记录，用于创建和更新
     * 保存时既保存在当前表中，同时保存在历史表中，历史表保存每次的更新记录
     * @param content
     * @param patientBean
     * @param version
     * @return
     */
    private IdType saveOrUpdate(String content, PatientBean patientBean, String version) {
        PatientBean patient = null;
        try {
            //保存在当前表
            patient = patientRespository.save(patientBean);
            logger.info("Save or update the current version of success");
        } catch (Exception e) {
            logger.error("Exception , Save or update the current version of error ", e );
        }
        if(patient!=null){
            String id = patient.getId();
            if(savePatientHistory(content,id,version)){// 保存历史记录
                return new IdType("Patient",id,version);
            }
        }
        return new IdType();
    }

    /**
     * 保存历史记录
     * @param content
     * @param id
     * @param version
     * @return
     */
    private boolean savePatientHistory(String content, String id, String version) {

        PatientHistoryBean patientHistoryBean = new PatientHistoryBean();
        patientHistoryBean.setContent(content);
        patientHistoryBean.setValidVersionId(id);
        patientHistoryBean.setCreateTime(new Date());
        patientHistoryBean.setVersion(version);

        PatientHistoryBean savePatientHistoryBean = null;
        try {
            savePatientHistoryBean = patientHistoryRespository.save(patientHistoryBean);
            logger.info("Save or update the historical version of success");
        } catch (Exception e) {
            logger.error("Exception , Save or update the historical version of error,", e);
        }
        return savePatientHistoryBean != null;
    }


    @Override
    public Patient getPatientById(String id) {
        Optional<PatientBean> result = null;
        try {
            result = patientRespository.findById(id);
            logger.info("Query the current version success, the patient id {}", id);
        } catch (Exception e) {
            logger.error("Exception, Query the current version error, the patient id {}" , e, id);
        }
        if (result.isPresent()) {
            PatientBean patientBean = result.get();
            return getPatient(patientBean.getContent(), id, patientBean.getVersion());
        } else {
            logger.info("Patient getPatientById  id={} is not exist!!!", id);
            return new Patient();
        }
    }







    @Override
    public Patient getPatientByIdAndVersion(String id, String version) {
        PatientHistoryBean patientHistoryBean = null;
        try {
            patientHistoryBean = patientHistoryRespository.findByValidVersionIdAndVersion(id, version);
            logger.info("Query the specified historical version success");
        } catch (Exception e) {
            logger.error("Exception, Query the specified historical version error, the id is {}, the version is {}",e, version);
        }
        if (patientHistoryBean != null) {
            return getPatient(patientHistoryBean.getContent(), id, version);
        } else {
            logger.info("patientHistoryRespository.findByValidVersionIdAndVersion Patient id={} is not exist!!!", id);
            return new Patient();
        }
    }

    private Patient getPatient(String content, String id, String version) {
//        FhirContext fhirContext = FhirContext.forDstu2();
////        This class is the FHIR JSON parser/encoder. Users should not interact with this class directly, but should use FhirContextContstant.newJsonParser() to get an instance.
////       IParser： 用于解析FHIR json ，fhirContext.newJsonParser() 来获取实例
//        IParser iParser = fhirContext.newJsonParser();


        Patient patient = FhirContextContstant.getParse().parseResource(Patient.class, content);
//        Patient patient = FhirContextContstant.forDstu2().newJsonParser().parseResource(Patient.class, content);
        IdType theId = new IdType("Patient", id, version);
        patient.setId(theId);
        patient.setMeta(new Meta().setLastUpdated(getLastUpdatTime(id)));
        return patient;
    }





    @Override
    public List<Patient> getPatientByName(StringParam pzatientName) {
        String name = pzatientName.getValue();
        List<PatientBean> patientBeanList = null;
        try {
            if (pzatientName.isExact()) {
                patientBeanList = patientRespository.findByName(name);
            } else {
                patientBeanList = patientRespository.findByNameLike(name);
            }
            logger.info("Query success based on name");
        } catch (Exception e) {
            logger.error("Exception, According to the name query error, the name is {}", name, e);
        }
        return getPatientList(patientBeanList);
    }

    /**
     * 返回集合
     * @param patientBeanList
     * @return
     */
    private List<Patient> getPatientList(List<PatientBean> patientBeanList) {
        if (CollectionUtils.isNotEmpty(patientBeanList)) {
            return patientBeanList.stream()
                    .filter(it -> it != null)
                    .map(it -> getPatient(it.getContent(), it.getId(), it.getVersion()))
                    .collect(Collectors.toList());
        } else {
            logger.info("getPatientList is empty");
            return Collections.emptyList();
        }
    }



    @Transactional
    @Override
    public Boolean deletePatient(String id) {

        Optional<PatientBean> result = null;
        try {
            //先查询是否存在
            result = patientRespository.findById(id);
        } catch (Exception e) {
            logger.error("Exception, Delete failure according to ID, the id is {}",id, e);
        }
        if (result.isPresent()) {
            try {
                //记录存在 删除当前表id信息
                //PatientBean patientBean = result.get();
                //设置删除时间
                //patientBean.setParam2(new Date());
                //patientBean.setParam3("1");
                patientRespository.deleteById(id);
                logger.info("deletePatient is success");
            } catch (Exception e) {
                logger.error("Exception, Delete historical version failure, the id is {}",id, e);
            }
            return true;
        } else {
            //记录不存在
            logger.info("deletePatient error , Patient id={} is not exist!!!", id);
            return false;
        }
    }


//    @Transactional
//    @Override
//    public Boolean deletePatient(Patient patient) {
//        //删除标记
//        Boolean deleteFlag = false;
//
//        IdType theId = patient.getIdElement();
//        String id = theId.getIdPart();
//        String version = theId.getVersionIdPart();
//
//        PatientHistoryBean historyEntity = null;
//        try {
//            //先查询是否存在
//            historyEntity = patientHistoryRespository.findByValidVersionIdAndVersion(id, version);
//        } catch (Exception e) {
//            e.printStackTrace();
//            logger.error("query error , the cause is {}",e.getCause());
//        }
//
//        //存储历史记录 标记
//        boolean saveFlag;
//        if (historyEntity == null) {
//            String content = FhirContextContstant.getParse().encodeResourceToString(patient);
//            saveFlag = saveHistoryPatient(content, id, version);
//        } else {
//            saveFlag = true;
//        }
//        if (saveFlag) {
//            try {
//                //删除当前表id信息
//                patientRespository.deleteById(id);
//            } catch (Exception e) {
//                e.printStackTrace();
//                logger.error("deletePatient error , the cause is {}",e.getCause());
//            }
//            deleteFlag = true;
//        }
//        return deleteFlag;
//    }




    @Override
    public Date getLastUpdatTime(String id) {
        Optional<PatientBean> result = patientRespository.findById(id);
        if (!result.isPresent()) {
            logger.info("Patient findById error, {} is not exist!!!", id);
            return new Date();
        }
        return result.get().getParam1();
    }

    @Override
    public Date getHistoryLastUpdatTime(String id, String version) {
        PatientHistoryBean result = patientHistoryRespository.findByValidVersionIdAndVersion(id, version);
        if(result!=null){
            return result.getCreateTime();
        } else {
            return null;
        }
    }

    @Override
    public List<Patient> getAllPatientById(String id) {
        List<PatientHistoryBean> patientList = patientHistoryRespository.findByValidVersionId(id);
        return getPatientHistoryLists(patientList);
    }


    /**
     * 返回历史集合
     * @param patientBeanList
     * @return
     */
    private List<Patient> getPatientHistoryLists(List<PatientHistoryBean> patientBeanList) {
        if (CollectionUtils.isNotEmpty(patientBeanList)) {
            logger.info("Query all historical versions of success");
            List<Patient> list = patientBeanList.stream()
                    .filter(it -> it != null)
                    .map(it -> getHistoryPatient(it.getContent(), it.getValidVersionId(), it.getVersion()))
                    .collect(Collectors.toList());

            return list;
        } else {
            logger.info("getPatientHistoryLists is empty!!!");
            return Collections.emptyList();
        }
    }

    private Patient getHistoryPatient(String content, String id, String version) {

        Patient patient = FhirContextContstant.getParse().parseResource(Patient.class, content);
        IdType theId = new IdType("Patient", id, version);
        patient.setId(theId);
        patient.setMeta(new Meta().setLastUpdated(getHistoryLastUpdatTime(id,version)));
        return patient;
    }
}
